/****************************************************************************
 *
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#pragma once

#include <QByteArray>
#include <QString>

#include <cmath>

#include "QGCTileSet.h" 
#include "QtLocation/private/qgeomaptype_p.h"

/**
 * @brief PNG图像签名标识
 */
static const unsigned char pngSignature[]  = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00};

/**
 * @brief JPEG图像签名标识
 */
static const unsigned char jpegSignature[] = {0xFF, 0xD8, 0xFF, 0x00};

/**
 * @brief GIF图像签名标识
 */
static const unsigned char gifSignature[]  = {0x47, 0x49, 0x46, 0x38, 0x00};

/**
 * @brief 默认瓦片大小（字节）
 * 表示地图瓦片的平均大小，用于缓存管理和存储估算
 * 这个值是经验值，根据不同的地图提供商实际测量得到的。
 * 这值主要用于：
 *      1.缓存大小的计算和管理
 *      2.存储空间的估算
 *      3.下载任务的进度计算
 *      4.内存使用量的预估
 */
static const quint32 AVERAGE_TILE_SIZE = 13652;

class QNetworkRequest;
class QNetworkAccessManager;

/**
 * @brief 地图提供商基类
 * 
 * MapProvider是所有地图提供商的抽象基类，定义了地图瓦片获取、坐标转换等通用接口。
 * 所有具体地图提供商（如Google、Bing、高德等）都需要继承此类并实现相应的虚函数。
 * 
 * 主要功能包括：
 * 1. 生成地图瓦片的网络请求
 * 2. 图像格式识别
 * 3. 地理坐标与瓦片坐标的相互转换
 * 4. 瓦片数量计算
 * 5. 提供地图相关的基本属性
 * 
 * 设计模式：抽象工厂模式，为不同地图提供商提供统一接口
 */
class MapProvider : public QObject {
    Q_OBJECT

public:
    /**
     * @brief 构造函数
     * @param referrer 请求来源URL，用于HTTP请求头中的Referrer字段
     * @param imageFormat 默认图像格式（如png、jpg等）
     * @param averageSize 平均瓦片大小（字节）
     * @param mapType 地图类型样式
     * @param parent 父对象指针
     */
    MapProvider(const QString& referrer, const QString& imageFormat, const quint32 averageSize,
        const QGeoMapType::MapStyle mapType = QGeoMapType::CustomMap, QObject* parent = nullptr);

    /**
     * @brief 获取地图瓦片的网络请求
     * @param x 瓦片X坐标
     * @param y 瓦片Y坐标
     * @param zoom 缩放级别
     * @param networkManager 网络管理器
     * @return QNetworkRequest 网络请求对象
     */
    virtual QNetworkRequest getTileURL(const int x, const int y, const int zoom, QNetworkAccessManager* networkManager);

    /**
     * @brief 根据图像数据识别图像格式
     * @param image 图像数据
     * @return QString 图像格式（如png、jpg、gif等）
     */
    QString getImageFormat(const QByteArray& image) const;

    /**
     * @brief 获取平均瓦片大小
     * @return quint32 平均瓦片大小（字节）
     */
    quint32 getAverageSize() const { return _averageSize; }

    /**
     * @brief 获取地图样式类型
     * @return QGeoMapType::MapStyle 地图样式类型
     */
    QGeoMapType::MapStyle getMapStyle() { return _mapType; }

    /**
     * @brief 将经度转换为瓦片X坐标
     * @param lon 经度
     * @param z 缩放级别
     * @return int 瓦片X坐标
     */
    virtual int long2tileX(const double lon, const int z) const;

    /**
     * @brief 将纬度转换为瓦片Y坐标
     * @param lat 纬度
     * @param z 缩放级别
     * @return int 瓦片Y坐标
     */
    virtual int lat2tileY(const double lat, const int z) const;

    /**
     * @brief 判断是否为高程图提供商
     * @return bool 是否为高程图提供商
     */
    virtual bool _isElevationProvider() const { return false; }
    
    /**
     * @brief 判断是否为必应地图提供商
     * @return bool 是否为必应地图提供商
     */
    virtual bool _isBingProvider() const { return false; }

    /**
     * @brief 计算指定区域的瓦片数量信息
     * @param zoom 缩放级别
     * @param topleftLon 左上角经度
     * @param topleftLat 左上角纬度
     * @param bottomRightLon 右下角经度
     * @param bottomRightLat 右下角纬度
     * @return QGCTileSet 瓦片集信息
     */
    virtual QGCTileSet getTileCount(const int zoom, const double topleftLon,
                                     const double topleftLat, const double bottomRightLon,
                                     const double bottomRightLat) const;

protected:
    /**
     * @brief 将瓦片坐标转换为四键值（QuadKey）
     * @param tileX 瓦片X坐标
     * @param tileY 瓦片Y坐标
     * @param levelOfDetail 缩放级别
     * @return QString 四键值字符串
     */
    QString _tileXYToQuadKey(const int tileX, const int tileY, const int levelOfDetail) const;
    
    /**
     * @brief 根据坐标计算服务器编号
     * @param x 瓦片X坐标
     * @param y 瓦片Y坐标
     * @param max 最大服务器数
     * @return int 服务器编号
     */
    int _getServerNum(const int x, const int y, const int max) const;
    
    /**
     * @brief 获取地图瓦片URL（纯虚函数，需要子类实现）
     * @param x 瓦片X坐标
     * @param y 瓦片Y坐标
     * @param zoom 缩放级别
     * @param networkManager 网络管理器
     * @return QString 瓦片URL
     */
    virtual QString _getURL(const int x, const int y, const int zoom, QNetworkAccessManager* networkManager) = 0;

    QString     _referrer;      ///< 请求来源URL，用于HTTP请求头中的Referrer字段
    QString     _imageFormat;   ///< 默认图像格式（如png、jpg等）
    quint32     _averageSize;   ///< 平均瓦片大小（字节）
    QByteArray  _userAgent;     ///< 用户代理字符串，用于HTTP请求头
    QString     _language;      ///< 语言设置，用于本地化请求
    QGeoMapType::MapStyle _mapType; ///< 地图类型样式

};
